﻿/* 
 * Copyright 2012 Pieter Roggemans
 *
 * This file is part of OWNMonitor.
 *
 * OWNMonitor is free software: you can redistribute it and/or modify it under 
 * the terms of the GNU General Public License as published by the Free Software 
 * Foundation, version 3 of the License.
 *
 * OWNMonitor is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with OWNMonitor. 
 * If not, see http://www.gnu.org/licenses/.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BTicino.BtCommLib.Domain.HighLevel;

namespace OWNLib
{
    public class OWNMessage
    {
        public static OWNRefData RefData;
        public static OWNProject ProjectData;

        public OWNMessage()
        {
            RefData = new OWNRefData();
            ProjectData = new OWNProject();

            try
            {  
                RefData.DeSerialize();
            }
            catch (Exception ex)
            {
            }
        }

        public string PrintMsgEventStatus(string direction, DefaultMsgEventStatus defaultMsgEventStatus)
        {
            MsgEventStatus msg = new MsgEventStatus(direction, defaultMsgEventStatus);
            return msg.ToString();
        }

        public class MsgEventStatus
        {
            public Direction Direction { get; set; }
            public Who Who { get; set; }
            public What What { get; set; }
            public Where Where { get; set; }
            public string RawMsg { get; set; }

            public MsgEventStatus(string direction, DefaultMsgEventStatus defaultMsgEventStatus)
            {
                Direction = new Direction(direction);
                Who = new Who(defaultMsgEventStatus.Who);
                What = new What(defaultMsgEventStatus.Who, defaultMsgEventStatus.What);
                Where = new Where(defaultMsgEventStatus.Who, defaultMsgEventStatus.Where);
                RawMsg = defaultMsgEventStatus.OpenRawMsg;
            }

            public override string ToString()
            {
                string retValue = "Direction: " + Direction.ToString() + " Who: " + Who.ToString();
                
                if(!string.IsNullOrEmpty(Where.WhereId))
                    retValue += ", Where: " + Where.ToString();

                if (!string.IsNullOrEmpty(What.WhatId))
                    retValue += ", What: " + What.ToString();

                return retValue;
            }
        }

        public string PrintMsgEventStatusDimension(string direction, DefaultMsgEventStatusDimension defaultMsgEventStatusDim)
        {
            MsgEventStatusDimension msg = new MsgEventStatusDimension(direction, defaultMsgEventStatusDim);
            return msg.ToString();
        }

        public class MsgEventStatusDimension
        {
            public Direction Direction { get; set; }
            public Who Who { get; set; }
            public Where Where { get; set; }
            public Dimension Dimension { get; set; }
            public string RawMsg { get; set; }

            public MsgEventStatusDimension(string direction, DefaultMsgEventStatusDimension defaultMsgEventStatusDim)
            {
                Direction = new Direction(direction);
                Who = new Who(defaultMsgEventStatusDim.Who);
                Dimension = new Dimension(defaultMsgEventStatusDim.Who, defaultMsgEventStatusDim.Dimension, defaultMsgEventStatusDim.DimValues);
                Where = new Where(defaultMsgEventStatusDim.Who, defaultMsgEventStatusDim.Where);
                RawMsg = defaultMsgEventStatusDim.OpenRawMsg;
            }

            public override string ToString()
            {
                string retValue = "Direction: " + Direction.ToString() + " Who: " + Who.ToString();

                if (!string.IsNullOrEmpty(Where.WhereId))
                    retValue += ", Where: " + Where.ToString();

                if (!string.IsNullOrEmpty(Dimension.DimId))
                    retValue += ", Dimension: " + Dimension.ToString();

                return retValue;
            }
        }

        public class Direction
        {
            public string Id { get; set; }

            public Direction(string id)
            {
                Id = id;
            }

            public string GetCode()
            {
                return RefData.FindDirection(Id).Code;
            }

            public override string ToString()
            {
                return GetCode() + " (" + Id + ")";
            }
        }

        public class Who
        {
            public string Id { get; set; }

            public Who(string id)
            {
                Id = id;
            }

            public string GetCode()
            {
                return RefData.FindWho(Id).Code;
            }

            public override string ToString()
            {
                if (Id == "")
                    return "-";
                else
                    return this.GetCode() + " (" + this.Id + ")";
            }
        }

        public class What
        {
            public string WhoId { get; set; }
            public string WhatId { get; set; }

            public What(string whoId, string whatId)
            {
                WhoId = whoId;
                WhatId = whatId;
            }

            public string GetCode()
            {
                return RefData.FindWhat(WhoId, WhatId).Code;
            }

            public override string ToString()
            {
                if (WhatId == "")
                    return "-";
                else
                    return this.GetCode() + " (" + this.WhatId + ")";
            }
        }

        public class Where
        {
            public string WhoId { get; set; }
            public string WhereId { get; set; }

            public Where(string whoId, string whereId)
            {
                WhoId = whoId;
                WhereId = whereId;
            }

            public string GetCode()
            {
                return ProjectData.FindWhere(WhoId, WhereId).Code;
            }

            public override string ToString()
            {
                if (WhereId == "")
                    return "-";
                else
                    return this.GetCode() + " (" + this.WhereId + ")";
            }
        }

        public class Dimension
        {
            public string WhoId { get; set; }
            public string DimId { get; set; }
            public List<DimValue> Values { get; set; }

            public Dimension(string whoId, string dimId, string[] values)
            {
                WhoId = whoId;
                DimId = dimId;
                Values = new List<DimValue>();
                foreach (string value in values)
                {
                    Values.Add(new DimValue(value));
                }
            }

            public string GetCode()
            {
                return RefData.FindDimension(WhoId, DimId).Code;
            }

            public string GetFormatMask()
            {
                return RefData.FindDimension(WhoId, DimId).FormatMask;
            }

            public override string ToString()
            {
                return this.GetCode() + " (" + DimId + "): " + this.GetFormattedValues();
            }

            private string GetFormattedValues()
            {
                if (Values.Count == 0)
                    return "()";

                string returnValue = "";
                    
                if (this.GetFormatMask() != "")
                {
                    try
                    {
                        string retVal = string.Format(this.GetFormatMask(), Values.ToArray());
                        return retVal;
                    }
                    catch(Exception ex)
                    {
                        returnValue += "Error using format mask <" + this.GetFormatMask() + "> " + ex.Message + " on ";
                    }
                }

                returnValue += "(";
                for (int i = 0; i < Values.Count; i++)
                {
                    returnValue += Values[i].ToString();

                    if (i < Values.Count - 1)
                        returnValue += ", ";
                    else
                        returnValue += ")";
                }
                return returnValue;
            }
        }

        public class DimValue : IFormattable
        {
           private string _value;

           public DimValue(string value)
           {
               this._value = value;
           }

           public decimal Celsius
           {
               get { return int.Parse(this._value)/10; }
           }

           public string DayOfWeek
           {
               get 
               {
                   int dayNb = int.Parse(this._value);
                   DateTime date = DateTime.Now;

                   while (date.DayOfWeek != (DayOfWeek)dayNb)
                       date = date.AddDays(1D);

                   return date.ToString("dddd");
               }
           }

           public string TimeZone
           {
               get 
               {
                   int hours = int.Parse(this._value);
                   if (hours == 0)
                       return "GMT";
                   else if (hours > 0)
                       return "GMT +" + hours;
                   else
                        return "GMT " + hours;
               }
           }

           public string Model
           { 
               get 
                {
                  switch(_value)
                  {
                      case "2":
                          return "MHServer";
                      case "4":
                          return "MH200";
                      case "6":
                          return "F452";
                      case "7":
                          return "F452V";
                      case "11":
                          return "MHServer2";
                      case "13":
                          return "H4684";
                      default:
                          return "Unknown";
                  }
                }
            }

           public override string ToString()
           {
               return this.ToString("G", null);
           }

           public string ToString(string format)
           {
               return this.ToString(format, null);
           }

           public string ToString(string format, IFormatProvider provider)
           {  
              // Handle null or empty string.
              if (String.IsNullOrEmpty(format)) 
                  format = "G";

              // Remove spaces and convert to uppercase.
              format = format.Trim().ToUpperInvariant();

              // If no provider provided...
              if (provider == null)
                  provider = System.Globalization.NumberFormatInfo.CurrentInfo;

              switch (format)
              {
                 // return temperature in Celsius.
                 case "CELSIUS":
                    return this.Celsius.ToString("N1") + " °C";
                 case "TIMEZONE":
                    return this.TimeZone;
                 case "DAYOFWEEK":
                    return this.DayOfWeek;
                 case "MODEL":
                    return this.Model;
                 case "G":
                    return this._value;
                 default:
                    throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
              }      
           }
        }
    }
}